﻿Imports System.Security.Cryptography
Imports System.Security.Cryptography.Xml
Imports System.Xml


Public Class Boss
    Implements IDisposable

    Private RSAKey As RSACryptoServiceProvider = RSACryptoServiceProvider.Create
    Private KeyPath As String
    Public Sub New()

        If System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed Then
            KeyPath = IO.Path.Combine(System.Deployment.Application.ApplicationDeployment.CurrentDeployment.DataDirectory, My.Resources.BossFile)
        Else
            Dim installType As InstallTypes = [Enum].Parse(GetType(InstallTypes), My.Settings.InstallType)
            If installType = InstallTypes.MSI Then
                KeyPath = IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "VBJay Solutions\Employee Scheduler\" & My.Resources.BossFile)
            Else
                KeyPath = My.Resources.BossFile
            End If
            LoadPrivateKey(KeyPath)

        End If
    End Sub

    Public Sub LoadPrivateKey(ByVal pth As String)
        If Not IO.File.Exists(pth) Then
            GenerateKey(pth)

        End If
        Dim xmdoc As New System.Xml.XmlDocument
        xmdoc.Load(pth)
        Try
            RSAKey.FromXmlString(xmdoc.OuterXml)
        Catch ex As Exception
            RSACryptoServiceProvider.UseMachineKeyStore = True
            RSAKey = RSACryptoServiceProvider.Create
            RSAKey.FromXmlString(xmdoc.OuterXml)
        Finally
            RSACryptoServiceProvider.UseMachineKeyStore = False
        End Try




    End Sub
    Public Sub SavePublicKey(ByVal pth As String)
        Dim xmlDoc As New System.Xml.XmlDocument
        xmlDoc.PreserveWhitespace = True
        xmlDoc.LoadXml(RSAKey.ToXmlString(False))
        xmlDoc.Save(pth)
    End Sub
    Public Sub SavePrivateKey(ByVal Path As String)
        Try
            IO.File.Copy(KeyPath, IO.Path.Combine(Path, IO.Path.GetFileName(KeyPath)))
        Catch ex As Exception

        End Try
    End Sub
    Public Sub GenerateKey(ByVal pth As String)
        Dim xmlDoc As New System.Xml.XmlDocument
        Try
            RSAKey = RSACryptoServiceProvider.Create
            xmlDoc.PreserveWhitespace = True
            xmlDoc.LoadXml(RSAKey.ToXmlString(True))
        Catch ex As Exception
            RSACryptoServiceProvider.UseMachineKeyStore = True
            RSAKey = RSACryptoServiceProvider.Create
            xmlDoc.PreserveWhitespace = True
            xmlDoc.LoadXml(RSAKey.ToXmlString(True))
        Finally
            RSACryptoServiceProvider.UseMachineKeyStore = False
        End Try

        xmlDoc.Save(pth)

    End Sub
    'http://blogs.msdn.com/alejacma/archive/2008/02/07/how-to-sign-an-xml-and-verify-the-signature-with-net-vb-net.aspx
    Public Sub SignDoc(ByRef Doc As System.Xml.XmlDocument)
        Dim sig As New SignedXml(Doc)
        sig.SigningKey = RSAKey
        Dim reference As New Reference
        reference.Uri = ""
        Dim trns As New XmlDsigC14NTransform
        reference.AddTransform(trns)
        Dim env As New XmlDsigEnvelopedSignatureTransform
        reference.AddTransform(env)
        sig.AddReference(reference)
        Dim keyInfo As New KeyInfo
        keyInfo.AddClause(New RSAKeyValue(RSAKey))
        sig.KeyInfo = keyInfo
        sig.ComputeSignature()
        Dim xmlDigitalSignature As System.Xml.XmlElement = sig.GetXml()

        Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, True))

    End Sub
    Public Function IsSigned(ByVal pth As String) As Boolean
        Try
            Dim doc As New System.Xml.XmlDocument
            doc.PreserveWhitespace = True
            doc.Load(pth)
            ' Find the "Signature" node and create a new XmlNodeList object.
            '
            Dim nodeList As XmlNodeList = doc.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#")
            Return nodeList.Count <> 0


        Catch ex As Exception
            Return False
        End Try

    End Function

    Public Function VerifySignature(ByVal pth As String) As Boolean
        Try
            Dim doc As New System.Xml.XmlDocument
            doc.PreserveWhitespace = True
            doc.Load(pth)
            If TypeOf doc.FirstChild Is XmlDeclaration Then
                doc.RemoveChild(doc.FirstChild)
            End If




            ' Find the "Signature" node and create a new XmlNodeList object.
            '
            Dim nodeList As XmlNodeList = doc.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#")
            If nodeList.Count = 0 Then Return False

            Dim signedXml As New SignedXml(doc)
            signedXml.LoadXml(CType(nodeList(0), XmlElement))
            Return signedXml.CheckSignature




        Catch ex As Exception
            Return False
        End Try

    End Function
    Public Function VerifySignature(ByVal pth As String, ByVal key As String) As Boolean
        Try
            Dim doc As New System.Xml.XmlDocument
            doc.PreserveWhitespace = True
            doc.Load(pth)
            If TypeOf doc.FirstChild Is XmlDeclaration Then
                doc.RemoveChild(doc.FirstChild)
            End If




            ' Find the "Signature" node and create a new XmlNodeList object.
            '
            Dim nodeList As XmlNodeList = doc.GetElementsByTagName("Signature", "http://www.w3.org/2000/09/xmldsig#")
            If nodeList.Count = 0 Then Return False

            Dim signedXml As New SignedXml(doc)
            signedXml.LoadXml(CType(nodeList(0), XmlElement))
            Dim rsak As RSACryptoServiceProvider = New RSACryptoServiceProvider()
            rsak.FromXmlString(key)
            Return signedXml.CheckSignature(rsak)




        Catch ex As Exception
            Return False
        End Try

    End Function

#Region "IDisposable Support"
    Private disposedValue As Boolean ' To detect redundant calls

    ' IDisposable
    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ' TODO: dispose managed state (managed objects).
                RSAKey.Dispose()

            End If

            ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
            ' TODO: set large fields to null.
        End If
        Me.disposedValue = True
    End Sub

    ' TODO: override Finalize() only if Dispose(ByVal disposing As Boolean) above has code to free unmanaged resources.
    'Protected Overrides Sub Finalize()
    '    ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
    '    Dispose(False)
    '    MyBase.Finalize()
    'End Sub

    ' This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

End Class
